/*************************************************************************
 *
 *  Copyright (C) 2013 Florian Dang <florian.coin@gmail.com>
 *
 *  This file is part of NatusVerse.
 *
 *  NatusVerse is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  NatusVerse is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with NatusVerse.  If not, see <http://www.gnu.org/licenses/>.
 *
 *************************************************************************/

#ifndef INC_RAYTRACER_OBJECTS_CAMERA_H_
#define INC_RAYTRACER_OBJECTS_CAMERA_H_

/*!
 * \file        camera.h
 * \brief       Camera
 * \author      Florian Dang
 * \date        2013
 */

#include "raytracer/objects/point.h"

namespace raytracer
{
//! Camera/eye/observer class
/*!
  Simple camera inspired by http://courses.csusm.edu/cs697exz/camera.html
*/
class Camera
{
	public:
		//! constructors
		Camera() {}

		// Distance of look_at
		Camera(Point eye0, float dist_vanishing, Point view_up0, float fov0, int w0, int h0)
			: eye_(eye0), view_up_(view_up0), fov_(fov0), w_(w0), h_(h0)
		{
			Point vanish = eye() + dist_vanishing * look_at().Normalize();
			set_look_at(vanish);
		}

		Camera(Point eye0, Point look_at0, Point view_up0, float fov0, int w0, int h0)
			: eye_(eye0), look_at_(look_at0), view_up_(view_up0), fov_(fov0), w_(w0), h_(h0) {}

		//! destructors
		~Camera() {}

		//! accessors
		inline Point  eye() const { return eye_; }
		inline Vector look_at() const { return look_at_; }
		inline Point  view_up() const { return view_up_; }
		inline float  fov() const { return fov_; }

		inline int w() const { return w_; }
		inline int h() const { return h_; }

		//! mutators
		inline void set_eye(Point eye0) { eye_ = eye0; }
		inline void set_look_at(Vector lookat0) { look_at_ = lookat0; }

		Vector ViewDir() const;
		Vector XAxisDir() const;
		Vector UpAxisDir() const;
		Vector Xinc() const;
		Vector Yinc() const;

		void Debug() const;
		void Print() const;

	private:
		Point eye_;	    /*!< The "look from" camera/eye point */
		Point look_at_; /*!< "look at" point */
		Point view_up_; /*!< vanishing point */
		float fov_;     /*!< field of view */

		int w_;
		int h_;
};
}


#endif  // INC_RAYTRACER_OBJECTS_CAMERA_H_
